package org.jsequences;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ImmutableSortedSet;

/**
 * This class contains static methods which return empty immutable constants for different
 * datastructures. The reason for the existence of this class is java's stupid typesystem:
 * Since java does not support target typing in versions prior to 8, often generic arguments for
 * generic methods are incorrectly inferred.
 * <p>
 * Take this example:
 * 
 * <pre class="code">
 * <code class="java">
 *   <i>// This works:</i>
 *   List&lt;String&gt; stringList = Empty.list();
 *   
 *   <i>// This doesn't. The inferred type on the right side is  List&lt;Object&gt;</i>
 *   List&lt;String&gt; stringList = Lists.reverse(Empty.list());
 *   
 *   <i>// Instead, the generic type arguments must be specified manually:</i>
 *   List&lt;String&gt; stringList = Lists.reverse(Empty.&lt;String&gt;list());
 * </code>
 * </pre>
 * 
 * The reason is that java is only able to infer generic arguments in the most simple cases. The
 * worst part, however is that you <b>cannot</b> infer generics on static imports, so:
 * 
 * <pre class="code">
 * <code class="java">
 *   <b>import static</b> Empty.list;
 * 
 *   <i>// No way to specify generic type arguments without mentioning the containing class!
 *   // This isn't valid java:</i>
 *   List&lt;String&gt; stringList = Lists.reverse(&lt;String&gt; list());
 * </code>
 * </pre>
 * 
 * @author Eric Giese
 */
public final class Empty {

    /**
     * Returns the empty list.
     */
    public static <E> ImmutableList<E> list() {
        return ImmutableList.of();
    }

    /**
     * Returns the empty set.
     */
    public static <E> ImmutableSet<E> set() {
        return ImmutableSet.of();
    }

    /**
     * Returns the empty sorted set.
     */
    public static <E> ImmutableSortedSet<E> sortedSet() {
        return ImmutableSortedSet.of();
    }

    /**
     * Returns the empty map.
     */
    public static <K, V> ImmutableMap<K, V> map() {
        return ImmutableMap.of();
    }

    /**
     * Returns the empty sorted map.
     */
    public static <K, V> ImmutableSortedMap<K, V> sortedMap() {
        return ImmutableSortedMap.of();
    }

    private Empty() {}
}
